<?php

trait CoreTraitTimer
{

    private int $times = 0;
    private array $timeStack = [];
    private array $execStack = [];

    public function begin($i = 0)
    {
        if ($i == 0) {
            $this->times = 0;
            $this->timeStack = [];
            $this->execStack = [];
        }
        return $this->timeStack[$i] = microtime(true);
    }

    public function record(): string
    {
        $pre = $this->timeStack[$this->times];
        $now = $this->begin(++$this->times);
        return $this->execStack[$this->times] = $this->number_format($now - $pre);
    }

    public function end($format = true): string
    {
        $end = $this->number_format(end($this->timeStack) - $this->timeStack[0]);
        if ($format) $end = readableTime($end);
        return $end;
    }

    public function average(): string
    {
        return readableTime($this->number_format(array_sum($this->execStack) / $this->times));
    }

    public function number_format($num, int $decimals = 6, ?string $decimal_separator = '.', ?string $thousands_separator = ''): string
    {
        return number_format($num, $decimals, $decimal_separator, $thousands_separator);
    }

    public function max()
    {
        return readableTime(max($this->execStack));
    }

    public function getTimes(): int
    {
        return $this->times;
    }

    public function exec(): array
    {
        $fn = fn($time) => readableTime($this->number_format($time));
        return array_map($fn, $this->execStack);
    }

}